package com.bk.bookviews.service.impl;

import com.bk.bookviews.common.Constants;
import com.bk.bookviews.common.Pagination;
import com.bk.bookviews.domain.BookingOrder;
import com.bk.bookviews.domain.BookingOrderExample;
import com.bk.bookviews.domain.ScenicInfo;
import com.bk.bookviews.domain.UserInfo;
import com.bk.bookviews.exception.BusinessException;
import com.bk.bookviews.exception.BusinessExceptionEnum;
import com.bk.bookviews.mapper.BookingOrderMapper;
import com.bk.bookviews.mapper.ScenicInfoMapper;
import com.bk.bookviews.service.BookingOrderService;
import com.bk.bookviews.service.ScenicInfoService;
import com.bk.bookviews.util.DateUtil;
import com.bk.bookviews.util.RedisUtil;
import com.bk.bookviews.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@Service
public class BookingOrderServiceImpl implements BookingOrderService {

    @Resource
    private RedisUtil redisUtil;

    @Autowired
    private BookingOrderMapper  orderMapper;

    @Autowired
    private ScenicInfoMapper scenicInfoMapper;

    @Autowired
    private ScenicInfoService scenicInfoService;

    @Override
    public void saveOrder(BookingOrder bookingOrder, String token) {
        if (bookingOrder.getBookingTime().before(new Date())){
            throw new BusinessException(BusinessExceptionEnum.DATE_ERROR);
        }
        BookingOrderExample example = new BookingOrderExample();
        BookingOrderExample.Criteria criteria = example.createCriteria();
        ScenicInfo scenicInfo = scenicInfoMapper.selectByPrimaryKey(bookingOrder.getScenicId());
        if (scenicInfo == null){
            throw new BusinessException(BusinessExceptionEnum.SCENIC_NOT_EXIST);
        }
        if(!Constants.SCENIC_STATUS_NORMAL.equals(scenicInfo.getScenicStatus())){
            throw new BusinessException(BusinessExceptionEnum.SCENIC_STATU_ERROR);
        }
        criteria.andScenicIdEqualTo(bookingOrder.getScenicId());
        criteria.andBookingTimeEqualTo(bookingOrder.getBookingTime());
        criteria.andBookingStatusIn(Constants.BOOK_SUUCCESS);
        List<BookingOrder> bookingOrders = orderMapper.selectByExample(example);
        if (bookingOrders.size() >= scenicInfo.getLimitUsernum()){
            throw new BusinessException(BusinessExceptionEnum.SCENIC_BOOK_IS_FULL);
        }
        bookingOrder.setBookingStatus(Constants.BOOKING_STATUS_SUCCESS);
        bookingOrder.setCreateTime(new Date());
        UserInfo userInfo = (UserInfo) redisUtil.get(token);
        if (userInfo == null){
            throw new BusinessException(BusinessExceptionEnum.LOGON_FAILURE);
        }
        BookingOrderExample example2 = new BookingOrderExample();
        BookingOrderExample.Criteria criteria2 = example2.createCriteria();
        criteria2.andScenicIdEqualTo(bookingOrder.getScenicId());
        criteria2.andBookingTimeEqualTo(bookingOrder.getBookingTime());
        criteria2.andUserPhoneEqualTo(userInfo.getUserPhone());
        criteria2.andBookingStatusIn(Constants.BOOK_SUUCCESS);
        List<BookingOrder> bookingOrdersBySelf = orderMapper.selectByExample(example2);
        //如果本人当天已经预定过，不能重复预定
        if (!CollectionUtils.isEmpty(bookingOrdersBySelf)){
            throw new BusinessException(BusinessExceptionEnum.SCENIC_BOOK_IS_REPEAT);
        }

        bookingOrder.setUserId(userInfo.getUserId());
        bookingOrder.setUserPhone(userInfo.getUserPhone());
        bookingOrder.setPrice(scenicInfo.getScenicPrice());
        orderMapper.insertSelective(bookingOrder);
    }

    @Override
    public void updateOrder(BookingOrder bookingOrder) {
        BookingOrder bookingOrder1 = orderMapper.selectByPrimaryKey(bookingOrder.getOrderId());
        if (bookingOrder1 == null){
            throw new BusinessException(BusinessExceptionEnum.ORDER_NOT_EXIST);
        }
        if (bookingOrder1.getBookingTime().before(new Date())){
            throw new BusinessException(BusinessExceptionEnum.BOOK_TIME_OUT);
        }
        orderMapper.updateByPrimaryKeySelective(bookingOrder);
    }

    @Override
    public BookingOrder selectOrder(String orderId, String token) {
        BookingOrder bookingOrder = orderMapper.selectByPrimaryKey(Long.parseLong(orderId));
        ScenicInfo scenicInfo = scenicInfoService.selectScenic(bookingOrder.getScenicId(), token);
        bookingOrder.setScenicInfo(scenicInfo);
        return bookingOrder;
    }

    @Override
    public void checkOrder(BookingOrder bookingOrder) {
        if (bookingOrder.getBookingTime().before(new Date())){
            throw new BusinessException(BusinessExceptionEnum.DATE_ERROR);
        }
        BookingOrderExample example = new BookingOrderExample();
        BookingOrderExample.Criteria criteria = example.createCriteria();
        criteria.andScenicIdEqualTo(bookingOrder.getScenicId());
        criteria.andBookingTimeEqualTo(bookingOrder.getBookingTime());
        criteria.andBookingStatusIn(Constants.BOOK_SUUCCESS);
        ScenicInfo scenicInfo = bookingOrder.getScenicInfo();
        List<BookingOrder> bookingOrders = orderMapper.selectByExample(example);
        if (bookingOrders.size() >= scenicInfo.getLimitUsernum()){
            throw new BusinessException(BusinessExceptionEnum.SCENIC_BOOK_IS_FULL);
        }
    }

    @Override
    public Pagination selectOrderList(String token, BookingOrder bookingOrder) {
        BookingOrderExample example = new BookingOrderExample();
        BookingOrderExample.Criteria criteria = example.createCriteria();
        if (Constants.QUERY_SOURCE.equals(bookingOrder.getSource())){
            UserInfo userInfo = (UserInfo) redisUtil.get(token);
            if (userInfo == null){
                throw new BusinessException(BusinessExceptionEnum.LOGON_FAILURE);
            }
            criteria.andUserIdEqualTo(userInfo.getUserId());
        }
        if (bookingOrder.getOrderId() != null){
            criteria.andOrderIdEqualTo(bookingOrder.getOrderId());
        }
        if (StringUtil.isNotBlank(bookingOrder.getBookingStatus())){
            criteria.andBookingStatusEqualTo(bookingOrder.getBookingStatus());
        }
        if (StringUtil.isNotBlank(bookingOrder.getPayType())){
            criteria.andPayTypeEqualTo(bookingOrder.getPayType());
        }
        if (bookingOrder.getUserId() != null){
            criteria.andUserIdEqualTo(bookingOrder.getUserId());
        }
        if (StringUtil.isNotBlank(bookingOrder.getUserPhone())){
            criteria.andUserPhoneLike("%"+bookingOrder.getUserPhone()+"%");
        }
        if (bookingOrder.getBookingTime() != null){
            criteria.andCreateTimeLessThanOrEqualTo(bookingOrder.getBookingTime());
        }
        example.setOrderByClause("create_time desc");
        List<BookingOrder> bookingOrders = orderMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(bookingOrders)){
            for (BookingOrder order:bookingOrders) {
                ScenicInfo scenicInfo = scenicInfoService.selectScenic(order.getScenicId(), token);
                order.setScenicInfo(scenicInfo);
            }
        }
        return new Pagination(bookingOrders);
    }

    @Override
    public void payOrder(BookingOrder bookingOrder) {
        if(bookingOrder.getOrderId() == null){
            throw new BusinessException(BusinessExceptionEnum.ORDER_ID_IS_NULL);
        }
        bookingOrder = orderMapper.selectByPrimaryKey(bookingOrder.getOrderId());
        if (!Constants.BOOKING_STATUS_SUCCESS.equals(bookingOrder.getBookingStatus())){
            throw new BusinessException(BusinessExceptionEnum.ORDER_STATUS_ERROR);
        }
        bookingOrder.setBookingStatus(Constants.BOOKING_STATUS_PAY_SUCCESS);
        bookingOrder.setUpdateTime(new Date());
        orderMapper.updateByPrimaryKeySelective(bookingOrder);
    }
}
